﻿ #region Disclaimer/Info
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 //
 //   File:		HttpHandlerBase.cs
 //   Website:		http://dexterblogengine.com/
 //   Authors:		http://dexterblogengine.com/About.ashx
 //   Rev:		1
 //   Created:		19/01/2011
 //   Last edit:		19/01/2011
 //   License:		GNU Library General Public License (LGPL)
 // 
 //   For updated news and information please visit http://dexterblogengine.com/
 //   Dexter is hosted to Codeplex at http://dexterblogengine.codeplex.com
 //   For any question contact info@dexterblogengine.com
 //
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #endregion

using System;
using System.IO.Compression;
using System.Net;
using System.Text;
using System.Web;
using Dexter.Dependency;
using Dexter.Services;

namespace Dexter.Web.HttpHandlers {
	#region Usings

	

	#endregion

	///<summary>
	///	The base class for the HttpHandlers
	///</summary>
	public abstract class HttpHandlerBase : IHttpHandler {
		protected readonly IConfigurationService SiteConfigurationService;
		HttpContextWrapper wrapper;

		/// <summary>
		/// 	Initializes a new instance of the <see cref = "HttpHandlerBase" /> class.
		/// </summary>
		protected HttpHandlerBase ( ) {
			SiteConfigurationService = DexterContainer.Resolve <IConfigurationService> ( );
		}

		/// <summary>
		/// 	Initializes a new instance of the <see cref = "HttpHandlerBase" /> class.
		/// </summary>
		/// <param name = "siteConfigurationService">The site configuration service.</param>
		protected HttpHandlerBase ( IConfigurationService siteConfigurationService ) {
			this.SiteConfigurationService = siteConfigurationService;
		}

		#region IHttpHandler Members

		/// <summary>
		/// 	Gets a value indicating whether another request can use the <see cref = "T:System.Web.IHttpHandler" /> instance.
		/// </summary>
		/// <value></value>
		/// <returns>true if the <see cref = "T:System.Web.IHttpHandler" /> instance is reusable; otherwise, false.
		/// </returns>
		public virtual bool IsReusable {
			get { return false; }
		}

		/// <summary>
		/// 	Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref = "T:System.Web.IHttpHandler" /> interface.
		/// </summary>
		/// <param name = "context">An <see cref = "T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
		public void ProcessRequest ( HttpContext context ) {
			wrapper = new HttpContextWrapper ( context );

			if ( SiteConfigurationService.Configuration.AdvancedFeatues.DataCompression ) {
				AddCompression ( wrapper.Request , wrapper.Response );
			}

			ProcessRequest ( wrapper );
		}

		#endregion

		/// <summary>
		/// 	Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref = "T:System.Web.IHttpHandler" /> interface.
		/// </summary>
		/// <param name = "context">An <see cref = "T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
		public abstract void ProcessRequest ( HttpContextBase context );

		static void AddCompression ( HttpRequestBase request , HttpResponseBase response ) {
			string acceptEncoding = request.Headers[ "Accept-Encoding" ];

			if ( string.IsNullOrEmpty ( acceptEncoding ) ) {
				return;
			}

			acceptEncoding = acceptEncoding.ToUpperInvariant ( );

			if ( acceptEncoding.Contains ( "GZIP" ) ) {
				response.AppendHeader ( "Content-encoding" , "gzip" );
				response.Filter = new GZipStream ( response.Filter , CompressionMode.Compress );
			}
			else if ( acceptEncoding.Contains ( "DEFLATE" ) ) {
				response.AppendHeader ( "Content-encoding" , "deflate" );
				response.Filter = new DeflateStream ( response.Filter , CompressionMode.Compress );
			}
		}

		protected void AddHeaders ( string contentType , int cacheDays , int hashCode ) {
			wrapper.Response.ContentType = contentType;
			wrapper.Response.ContentEncoding = Encoding.UTF8;

			wrapper.Response.Cache.VaryByHeaders[ "Accept-Encoding" ] = true;
			wrapper.Response.Cache.SetCacheability ( HttpCacheability.Public );
			wrapper.Response.Cache.SetExpires ( DateTime.Now.AddDays ( cacheDays ) );
			wrapper.Response.Cache.SetMaxAge ( new TimeSpan ( cacheDays , 0 , 0 , 0 ) );
			wrapper.Response.Cache.SetRevalidation ( HttpCacheRevalidation.AllCaches );

			string etag = string.Concat ( "\"" , hashCode , "\"" );
			string incomingEtag = wrapper.Request.Headers[ "If-None-Match" ];

			wrapper.Response.Cache.SetETag ( etag );
			wrapper.Response.Cache.SetCacheability ( HttpCacheability.Public );

			if ( String.Compare ( incomingEtag , etag ) == 0 ) {
				wrapper.Response.Clear ( );
				wrapper.Response.StatusCode = ( int ) HttpStatusCode.NotModified;
				wrapper.Response.SuppressContent = true;
			}
		}
	}
}
